package se.jocke.tg;

import java.util.Collections;
import java.util.List;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import org.netbeans.editor.BaseDocument;
import org.netbeans.modules.editor.indent.api.Reformat;
import org.netbeans.spi.editor.codegen.CodeGenerator;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import se.jocke.tg.ui.GenerateTextDialog;

public class TextGenerator implements CodeGenerator {

    private final JTextComponent textComp;
    private final EditorStringFormater stringFormater;

    public enum FORMAT {
        STRING_BUILDER, COMMENT, DEFAULT
    }

    public TextGenerator(Lookup context) {
        textComp = context.lookup(JTextComponent.class);
        stringFormater = Lookup.getDefault().lookup(EditorStringFormater.class);
    }

    public static class Factory implements CodeGenerator.Factory {

        @Override
        public List<? extends CodeGenerator> create(Lookup context) {
            return Collections.singletonList(new TextGenerator(context));
        }
    }

    @Override
    public String getDisplayName() {
        return NbBundle.getMessage(getClass(), "display-name");
    }

    @Override
    public void invoke() {
        GenerateTextDialog dialog = GenerateTextDialog.getDefault();
        dialog.setTextGenerator(this);
        dialog.setLocationRelativeTo(null);
        dialog.setVisible(true);
        dialog.getEditorPane().requestFocus();
    }

    public void generateText(String text, FORMAT format) {
        try {
            insertText(text, format);
        } catch (BadLocationException ex) {
            Exceptions.printStackTrace(ex);
        }
    }

    private void insertText(String text, FORMAT format) throws BadLocationException {
        final String[] textRows = text.split("\n");

        switch (format) {
            case COMMENT:
                updateTextComp(stringFormater.formatCommentString(textRows));
                break;
            case STRING_BUILDER:
                updateTextComp(stringFormater.formatStringBuilderString(textRows));
                break;
            default:
                updateTextComp(stringFormater.formatDefaultString(textRows));
        }
    }

    private void updateTextComp(final String toInsert) throws BadLocationException {
        final int caretPosition = textComp.getCaretPosition();
        final BaseDocument baseDocument = (BaseDocument) textComp.getDocument();
        baseDocument.insertString(caretPosition, toInsert, null);
        reformatText(baseDocument, caretPosition, toInsert.length());
        textComp.requestFocus();
    }

    private void reformatText(final BaseDocument baseDocument, final int offset, final int endOffset) {
        final Reformat reformat = Reformat.get(baseDocument);
        reformat.lock();
        try {
            baseDocument.runAtomicAsUser(new Runnable() {

                @Override
                public void run() {
                    try {
                        reformat.reformat(offset, offset + endOffset);
                    } catch (BadLocationException ex) {
                        Exceptions.printStackTrace(ex);
                    }
                }
            });
        } finally {
            reformat.unlock();
        }
    }

}
